package com.xiguanlezz.cn.scanner;

import com.xiguanlezz.cn.ScannerConst;
import com.xiguanlezz.cn.JarReadUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Objects;

/**
 * @Author：习惯了种种
 * @CreateDate：2024/11/3 11:58
 * @Description：
 */
@Slf4j
public class BaseScanPackageClassProcessor implements ScanPackageClassAbility {

    @Override
    public void scanAndAddClassesInPackage(String scanPath, String packagePath, String packageName, List<String> classNameList) {
        File dir = new File(scanPath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 保留包路径下的class文件和文件目录
        File[] files = dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                boolean isDirectory = dir.isDirectory();
                boolean isClassFile = name.endsWith(".class");
                return isClassFile || isDirectory;
            }
        });
        if (isEmpty(files)) {
            return;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                String folderName = file.getName();
                scanAndAddClassesInPackage(
                        scanPath + File.separator + folderName,
                        packagePath + File.separator + folderName,
                        packageName + '.' + folderName, classNameList);
            } else {
                String fileName = file.getName();
                // 这里为什么需要分支区分jar还是file？因为如果包下面可能会有jar包
                if (fileName.endsWith(ScannerConst.CLASS_SUFFIX)) {
                    // 将x.class文件解析为com.xiguanlezz.cn.x，并放入classNameList中
                    String desName = packageName
                            + '.'
                            + fileName.substring(0, fileName.length() - ScannerConst.CLASS_SUFFIX.length());
                    classNameList.add(desName);
                } else if (fileName.endsWith(ScannerConst.JAR_SUFFIX)) {
                    // 将jar文件中的class文件解析为com.xiguanlezz.cn.x，并放入classNameList中
                    try {
                        JarReadUtils.getClassNameFromJar(packagePath, convertToJarURL(file), classNameList);
                    } catch (IOException e) {
                        log.warn("scanAndAddClassesInPackage ===> getClassNameFromJar error: {}", e);
                    }
                }
            }
        }
    }

    private static URL convertToJarURL(File file) throws MalformedURLException {
        String spec = String.format("%s:file:%s!/", ScannerConst.PROTOCOL_JAR, file.getAbsolutePath());
        return new URL(spec);
    }

    private static boolean isEmpty(File[] files) {
        return Objects.isNull(files) || files.length == 0;
    }
}
